.syntax unified

#define FLASH_BASE 0x40022000

#define FLASH_ACR (FLASH_BASE + 0x00)
#define FLASH_KEYR (FLASH_BASE + 0x04)
#define FLASH_OPTKEYR (FLASH_BASE + 0x08)
#define FLASH_SR (FLASH_BASE + 0x0c)
#define FLASH_CR (FLASH_BASE + 0x10)
#define FLASH_AR (FLASH_BASE + 0x14)
#define FLASH_OBR (FLASH_BASE + 0x1c)
#define FLASH_WRPR (FLASH_BASE + 0x20)

.section .vectors
.globl _start
_start:
_flash_init:
	b	flash_init
_flash_erase_all:
	b	flash_erase_all
_flash_erase_page:
	b	flash_erase_page
_flash_write_page:
	b	flash_write_page

.macro fwait, rega, regb
0:
	ldr	\rega, =FLASH_SR
	ldr	\regb, [\rega]
	tst \regb, #(1<<0) // busy
	bne	0b
.endm

.text
flash_init:
	/* unlock the flash controller */
	ldr	r0, =FLASH_KEYR
	ldr r1, =0x45670123
	ldr r2, =0xcdef89ab
	str	r1, [r0]
	str	r2, [r0]
	bx	lr

flash_erase_all:
	ldr	r0, =FLASH_CR
	mov	r1, #(1<<2) // mass erase
	str	r1, [r0]
	orr	r1, #(1<<6) // start
	str	r1, [r0]

	// wait for it to finish
	fwait r0, r1

	bx	lr

flash_erase_page:
	/* set the page erase bit */
	ldr	r1, =FLASH_CR
	mov	r2, #(1<<1) // page erase
	str	r2, [r1]

	/* write the address */
	ldr	r3, =FLASH_AR
	str	r0, [r3]

	/* start the erase */
	orr	r2, #(1<<6) // start
	str	r2, [r1]

	// wait for it to finish
	fwait r0, r1

	bx	lr

flash_write_page:
	/* set the programming bit */
	ldr	r1, =FLASH_CR
	mov	r2, #(1<<0)
	str	r2, [r1]

	/* start copying data */
	/* r0 holds destination */
	ldr	r1, =0x20008000 /* source */
	add r2, r1, $0x800  /* end at source */
.Lwriteloop:
	ldrh	r12, [r1], #2
	strh	r12, [r0], #2

	fwait r3, r4

	cmp		r2, r1
	bne		.Lwriteloop

	bx	lr

.ltorg

